package com.syf.disruptor;

import com.alibaba.fastjson.JSON;
import com.lmax.disruptor.EventHandler;
import com.syf.match.MatchServiceFactory;
import com.syf.match.MatchStrategy;
import com.syf.model.Order;
import com.syf.model.OrderBooks;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;


/**
 * 【8】定义--事件处理器(接口)的具体实现：
 *          MatchEngineAutoConfiguration 创建事件处理器[]:   多个EventHandler接口
 *              该对象 有多个 ---- 和Symbol交易对标识 的数据对应
 *              针对某一个OrderEventHandler ,同一时间只会有一个线程来执行它
 *
 *   并发的情况思考:
 *      1.OrderEventHandler：
 *          每个 Symbol 都有一个和它对应,它是个多例对象 -> 每一个OrderEventHandler 对应一个 Symbol
 *      2.OrderBooks：
 *          和一个交易对Symbol 绑定,没有线程安全问题
 *      3.MatchService：
 *          只有一个,若我们将 OrderBooks 当成它的一个属性,就会有并发问题(多个线程处理同一个公共对象),
 *          因此,我们的这个参数使用方法传递过去:
 */
@Data
@Slf4j
public class OrderEventHandler implements EventHandler<OrderEvent> {

    //创建OrderEventHandler时，构造器注入
    private OrderBooks orderBooks;    //每个 symbol交易对 对应一个 orderBooks
    private String symbol ;
    public OrderEventHandler(OrderBooks orderBooks) {   //在MatchEngineAutoConfiguration中 创建多个 EventHandler接口实现类
        this.orderBooks = orderBooks;
        this.symbol =  this.orderBooks.getSymbol() ;
    }

    /**
     * 监听、接收到了某个消息----处理【订阅消费】
     *          同一个“事件”可以有 多个消费者OrderEventHandler
     *
     *          每个 OrderEventHandler 就是一个线程
     *          可以接收到所有订单数据，有多个线程处理 --》 每个线程 只会处理 自己对应交易对的订单
     *
     * @param event 事件
     * @param sequence 递增的序号
     * @param endOfBatch
     * @throws Exception
     */
    @Override
    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {
        // 从ringbuffer 里面接收了某个数据
        Order order = (Order)event.getSource();

        // 校验是否是对应交易对(交易市场)：我们接收到了一个不属于我们处理的数据,我们不处理
        if(!order.getSymbol().equals(symbol)){
            return;  //每个线程 只会处理 自己对应交易对的订单【当前OrderEventHandler对应一个orderBooks和symbol】
        }
        log.info("====> 开始接受委托单{} <======", JSON.toJSONString(order));
        log.info("开始接收订单事件============>{}", event);


        try {
            //调用某种交易策略： LIMIT_PRICE策略 -》  对应策略实现类LimitPriceMatchServiceImpl -》 match撮合处理
            MatchServiceFactory.getMatchService(MatchStrategy.LIMIT_PRICE).match(orderBooks ,order);

        } catch (Exception e) {
            log.error(String.format("处理委托单：%s 发生了错误", JSON.toJSON(order)), e);
        } finally {

        }

        log.info("处理完成我们的订单事件===================>{}", event);
    }
}
